package cn.tang.tframe.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;

public class TryHelper {
	private static Logger logger = LoggerFactory.getLogger(TryHelper.class);
	private static int[] steps = new int[] { 1, 1, 2 };

	public static <T extends Serializable> TryResult<T> tryProcess(int times, Tryable<T> tryable) {
		int c = Math.max(times, 0);
		int time = 0;
		TryResult<T> tryResult = null;
		while (time++ < c) {
			try {
				tryResult = tryable.doTry(time);
			} catch (Exception e) {
				logger.error("dotry exception: ", new Object[] { e });
				continue;
			}
			if (null != tryResult && tryResult.isSuccess()) {
				return tryResult;
			}
			try {
				Thread.sleep(getStepIndex(time) * 1000);
			} catch (InterruptedException e) {
				// swollow
			}
		}
		if (null == tryResult) {
			tryResult = new TryResult<T>();
		}
		tryResult.setSuccess(false);
		return tryResult;
	}

	private static int getStepIndex(int times) {
		times = Math.max(0, times - 1);
		int stepsize = steps.length;
		return times % stepsize;
	}

	public static interface Tryable<T extends Serializable> {
		/**
		 *
		 * @param time
		 *            第几次执行
		 */
		public TryResult<T> doTry(int time);
	}

	public static class TryResult<T extends Serializable> implements Serializable {
		private static final long serialVersionUID = 1L;
		protected boolean success = true;
		protected T value;
		protected String errorCode;
		protected String errorMsg;

		public boolean isSuccess() {
			return success;
		}

		public void setSuccess(boolean success) {
			this.success = success;
		}

		public T getValue() {
			return value;
		}

		public void setValue(T value) {
			this.value = value;
		}

		public String getErrorCode() {
			return errorCode;
		}

		public void setErrorCode(String errorCode) {
			this.errorCode = errorCode;
		}

		public String getErrorMsg() {
			return errorMsg;
		}

		public void setErrorMsg(String errorMsg) {
			this.errorMsg = errorMsg;
		}

		@Override
		public String toString() {
			return "TryResult{" + "success=" + success + ", value=" + value + ", errorCode='" + errorCode + '\''
					+ ", errorMsg='" + errorMsg + '\'' + '}';
		}
	}

	public static void main(String[] args) {
		TryHelper.tryProcess(5, new Tryable() {
			@Override
			public TryResult doTry(int time) {
				System.out.println("times======" + time);
				System.out.println("do try");
				TryResult t = new TryResult();
				if (time == 4) {
					t.setSuccess(true);
					return t;
				}
				t.setSuccess(false);
				return t;
			}
		});
	}

}

